import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import '../../../shared/widgets/aurora_background.dart';
import '../../../shared/widgets/tts_control.dart';
import '../../../shared/utils/responsive_utils.dart';
import '../../../core/api/api_service.dart';
import '../../../shared/utils/sensitive_filter.dart';
import 'dart:io';
import 'dart:async';
import 'package:hive_flutter/hive_flutter.dart';

class CapturePage extends StatefulWidget {
  const CapturePage({super.key});

  @override
  State<CapturePage> createState() => _CapturePageState();
}

class _CapturePageState extends State<CapturePage> {
  final TextEditingController _messageController = TextEditingController();
  final ScrollController _scrollController = ScrollController();
  final List<ChatMessage> _messages = [];
  bool _isLoading = false;
  File? _pendingImage; // 待发送的图片
  String? _pendingImageUrl; // 服务器返回的图片URL
  String? _pendingFileId; // 服务器返回的文件ID
  bool _showScrollToBottom = false; // 是否显示回到底部按钮
  Timer? _typingTimer;

  String? _sessionId; // AI聊天会话ID

  @override
  void initState() {
    super.initState();
    // 根据本地年级信息自动设置敏感词等级（小学/初中/高中）
    try {
      final box = Hive.box('app');
      final dynamic userExtra = box.get('userExtraInfo');
      String? gradeName;
      if (userExtra is Map) {
        final dynamic g = userExtra['grade'];
        gradeName = g?.toString();
      } else if (userExtra != null) {
        gradeName = userExtra.toString();
      }
      SensitiveFilter.setStageByGradeName(gradeName);
    } catch (_) {}
    // 会话初始化：若本地已有则复用，否则创建
    try {
      final box = Hive.box('app');
      final String? savedConversationId =
          box.get('aiConversationId') as String?;
      if (savedConversationId != null && savedConversationId.isNotEmpty) {
        _sessionId = savedConversationId;
        print('🔁 复用本地会话ID: $_sessionId');
        try {
          _addSessionIdToList(savedConversationId);
        } catch (_) {}
      } else {
        _createChatSession();
      }
    } catch (e) {
      // 若本地存取异常，仍尝试创建会话
      print('⚠️ 会话本地读取异常，尝试创建新会话: $e');
      _createChatSession();
    }

    // 尝试从本地恢复聊天记录；若没有则添加欢迎语
    final bool restored = _restoreChatFromLocal();
    if (!restored) {
      _messages.add(
        ChatMessage(
          text: '你好！我是你的AI学习助手，可以帮你解答题目。',
          isUser: false,
          timestamp: DateTime.now(),
        ),
      );
    }
    // 输入变化时更新发送按钮可用态
    _messageController.addListener(() => setState(() {}));
    _scrollController.addListener(() {
      if (!_scrollController.hasClients) return;
      final double offset = _scrollController.offset;
      final double max = _scrollController.position.maxScrollExtent;
      final bool shouldShow = max - offset > 200;
      if (shouldShow != _showScrollToBottom) {
        setState(() {
          _showScrollToBottom = shouldShow;
        });
      }
    });
  }

  @override
  void dispose() {
    _messageController.dispose();
    _scrollController.dispose();
    _typingTimer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('AI学习助手'),
        backgroundColor: Theme.of(context).colorScheme.surface,
        foregroundColor: Theme.of(context).colorScheme.onSurface,
        elevation: 0,
        actions: [
          // 语音设置按钮
          IconButton(
            icon: const Icon(Icons.volume_up),
            onPressed: () => _showTTSSettings(context),
            tooltip: '语音设置',
          ),
          PopupMenuButton<String>(
            icon: const Icon(Icons.more_vert),
            onSelected: (value) async {
              switch (value) {
                case 'new_session':
                  await _startNewSession();
                  break;
                case 'history':
                  if (mounted) context.push('/ai/history');
                  break;
              }
            },
            itemBuilder:
                (context) => [
                  const PopupMenuItem<String>(
                    value: 'new_session',
                    child: Text('新会话'),
                  ),
                  const PopupMenuItem<String>(
                    value: 'history',
                    child: Text('历史记录'),
                  ),
                ],
          ),
        ],
      ),
      body: Column(
        children: [
          // 聊天消息列表
          Expanded(
            child: Stack(
              children: [
                const AuroraBackground(),
                ListView.builder(
                  controller: _scrollController,
                  padding: EdgeInsets.all(
                    ResponsiveUtils.getResponsiveSpacing(context, 12),
                  ),
                  itemCount: _messages.length + (_isLoading ? 1 : 0),
                  itemBuilder: (context, index) {
                    if (index < _messages.length) {
                      return _buildMessage(_messages[index]);
                    }
                    // 思考中提示
                    return _buildTypingIndicator(context);
                  },
                ),
                if (_showScrollToBottom)
                  Positioned(
                    right: ResponsiveUtils.getResponsiveSpacing(context, 12),
                    bottom: ResponsiveUtils.getResponsiveSpacing(context, 12),
                    child: FloatingActionButton.small(
                      heroTag: 'scroll_down_btn',
                      onPressed: _scrollToBottom,
                      child: const Icon(Icons.arrow_downward_rounded),
                    ),
                  ),
              ],
            ),
          ),
          // 输入区域
          _buildInputArea(),
        ],
      ),
    );
  }

  Widget _buildMessage(ChatMessage message) {
    final ColorScheme cs = Theme.of(context).colorScheme;
    return Padding(
      padding: EdgeInsets.only(
        bottom: ResponsiveUtils.getResponsiveSpacing(context, 12),
      ),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment:
            message.isUser ? MainAxisAlignment.end : MainAxisAlignment.start,
        children: [
          if (!message.isUser) ...[
            CircleAvatar(
              radius: ResponsiveUtils.getResponsiveIconSize(context, 16),
              backgroundColor: cs.primary,
              child: Icon(
                Icons.smart_toy,
                color: Colors.white,
                size: ResponsiveUtils.getResponsiveIconSize(context, 16),
              ),
            ),
            SizedBox(width: ResponsiveUtils.getResponsiveSpacing(context, 8)),
          ],
          Flexible(
            child: AnimatedScale(
              duration: const Duration(milliseconds: 180),
              scale: 1.0,
              child: Container(
                constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width * 0.78,
                ),
                padding: EdgeInsets.all(
                  ResponsiveUtils.getResponsiveSpacing(context, 12),
                ),
                decoration: BoxDecoration(
                  gradient:
                      message.isUser
                          ? LinearGradient(
                            colors: [cs.primary, cs.primaryContainer],
                            begin: Alignment.topLeft,
                            end: Alignment.bottomRight,
                          )
                          : null,
                  color: message.isUser ? null : cs.surfaceContainerHighest,
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(
                      message.isUser
                          ? ResponsiveUtils.getResponsiveRadius(context, 16)
                          : ResponsiveUtils.getResponsiveRadius(context, 6),
                    ),
                    topRight: Radius.circular(
                      message.isUser
                          ? ResponsiveUtils.getResponsiveRadius(context, 6)
                          : ResponsiveUtils.getResponsiveRadius(context, 16),
                    ),
                    bottomLeft: Radius.circular(
                      ResponsiveUtils.getResponsiveRadius(context, 16),
                    ),
                    bottomRight: Radius.circular(
                      ResponsiveUtils.getResponsiveRadius(context, 16),
                    ),
                  ),
                  boxShadow: [
                    BoxShadow(
                      color: (message.isUser ? cs.primary : cs.secondary)
                          .withOpacity(0.25),
                      blurRadius: 16,
                      spreadRadius: 0.5,
                    ),
                  ],
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    if (message.image != null) ...[
                      ClipRRect(
                        borderRadius: BorderRadius.circular(
                          ResponsiveUtils.getResponsiveRadius(context, 10),
                        ),
                        child: Image.file(
                          message.image!,
                          width: double.infinity,
                          fit: BoxFit.cover,
                        ),
                      ),
                      SizedBox(
                        height: ResponsiveUtils.getResponsiveSpacing(
                          context,
                          8,
                        ),
                      ),
                    ],
                    if (message.text.isNotEmpty) ...[
                      Text(
                        message.text,
                        style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                          color: message.isUser ? Colors.white : cs.onSurface,
                          height: 1.35,
                        ),
                      ),
                      // 为AI回复添加语音控制
                      if (!message.isUser) ...[
                        SizedBox(
                          height: ResponsiveUtils.getResponsiveSpacing(
                            context,
                            8,
                          ),
                        ),
                        TTSControl(
                          text: message.text,
                          onSpeakStart: () {
                            // 可以在这里添加语音开始时的逻辑
                          },
                          onSpeakEnd: () {
                            // 可以在这里添加语音结束时的逻辑
                          },
                        ),
                      ],
                    ],
                    const SizedBox(height: 4),
                    Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        if (!message.isUser)
                          Icon(
                            Icons.shield_moon,
                            size: ResponsiveUtils.getResponsiveIconSize(
                              context,
                              10,
                            ),
                            color: cs.onSurface.withOpacity(0.5),
                          ),
                        if (!message.isUser)
                          SizedBox(
                            width: ResponsiveUtils.getResponsiveSpacing(
                              context,
                              3,
                            ),
                          ),
                        Text(
                          _formatTime(message.timestamp),
                          style: Theme.of(
                            context,
                          ).textTheme.bodySmall?.copyWith(
                            color:
                                message.isUser
                                    ? Colors.white.withOpacity(0.75)
                                    : cs.onSurface.withOpacity(0.55),
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ),
          if (message.isUser) ...[
            SizedBox(width: ResponsiveUtils.getResponsiveSpacing(context, 8)),
            CircleAvatar(
              radius: ResponsiveUtils.getResponsiveIconSize(context, 18),
              backgroundColor: cs.secondary,
              child: Icon(
                Icons.person,
                color: Colors.white,
                size: ResponsiveUtils.getResponsiveIconSize(context, 18),
              ),
            ),
          ],
        ],
      ),
    );
  }

  Widget _buildInputArea() {
    return Container(
      padding: EdgeInsets.all(
        ResponsiveUtils.getResponsiveSpacing(context, 16),
      ),
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.surface,
        border: Border(
          top: BorderSide(
            color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
          ),
        ),
      ),
      child: SafeArea(
        child: Column(
          children: [
            // 待发送图片预览
            if (_pendingImage != null || _pendingImageUrl != null) ...[
              Container(
                margin: EdgeInsets.only(
                  bottom: ResponsiveUtils.getResponsiveSpacing(context, 12),
                ),
                padding: EdgeInsets.all(
                  ResponsiveUtils.getResponsiveSpacing(context, 8),
                ),
                decoration: BoxDecoration(
                  color: Theme.of(context).colorScheme.surfaceContainerHighest,
                  borderRadius: BorderRadius.circular(
                    ResponsiveUtils.getResponsiveRadius(context, 8),
                  ),
                ),
                child: Row(
                  children: [
                    ClipRRect(
                      borderRadius: BorderRadius.circular(
                        ResponsiveUtils.getResponsiveRadius(context, 4),
                      ),
                      child:
                          _pendingImageUrl != null
                              ? Image.network(
                                _pendingImageUrl!,
                                width: ResponsiveUtils.getResponsiveIconSize(
                                  context,
                                  60,
                                ),
                                height: ResponsiveUtils.getResponsiveIconSize(
                                  context,
                                  60,
                                ),
                                fit: BoxFit.cover,
                              )
                              : (_pendingImage != null
                                  ? Image.file(
                                    _pendingImage!,
                                    width:
                                        ResponsiveUtils.getResponsiveIconSize(
                                          context,
                                          60,
                                        ),
                                    height:
                                        ResponsiveUtils.getResponsiveIconSize(
                                          context,
                                          60,
                                        ),
                                    fit: BoxFit.cover,
                                  )
                                  : const SizedBox.shrink()),
                    ),
                    SizedBox(
                      width: ResponsiveUtils.getResponsiveSpacing(context, 12),
                    ),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            '已选择图片',
                            style: Theme.of(
                              context,
                            ).textTheme.bodyMedium?.copyWith(
                              fontWeight: FontWeight.w500,
                              color: Theme.of(context).colorScheme.onSurface,
                            ),
                          ),
                          SizedBox(
                            height: ResponsiveUtils.getResponsiveSpacing(
                              context,
                              4,
                            ),
                          ),
                          Text(
                            '点击发送按钮将图片和文字一起发送',
                            style: Theme.of(
                              context,
                            ).textTheme.bodySmall?.copyWith(
                              color: Theme.of(
                                context,
                              ).colorScheme.onSurface.withOpacity(0.6),
                            ),
                          ),
                        ],
                      ),
                    ),
                    IconButton(
                      onPressed: () {
                        setState(() {
                          _pendingImage = null;
                          _pendingImageUrl = null;
                          _pendingFileId = null;
                        });
                      },
                      icon: Icon(
                        Icons.close,
                        size: ResponsiveUtils.getResponsiveIconSize(
                          context,
                          20,
                        ),
                      ),
                      color: Theme.of(
                        context,
                      ).colorScheme.onSurface.withOpacity(0.6),
                    ),
                  ],
                ),
              ),
            ],
            // 输入区域
            Row(
              children: [
                // 图片上传按钮
                IconButton(
                  onPressed: _showImagePicker,
                  icon: Icon(
                    Icons.photo_camera,
                    size: ResponsiveUtils.getResponsiveIconSize(context, 26),
                  ),
                  color: Theme.of(context).colorScheme.primary,
                ),
                SizedBox(
                  width: ResponsiveUtils.getResponsiveSpacing(context, 8),
                ),
                // 文本输入框
                Expanded(
                  child: TextField(
                    controller: _messageController,
                    decoration: InputDecoration(
                      hintText:
                          _pendingImage != null ? '说说你遇到的难题吧' : '请输入问题...',
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(
                          ResponsiveUtils.getResponsiveRadius(context, 24),
                        ),
                        borderSide: BorderSide.none,
                      ),
                      enabledBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(
                          ResponsiveUtils.getResponsiveRadius(context, 24),
                        ),
                        borderSide: BorderSide.none,
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(
                          ResponsiveUtils.getResponsiveRadius(context, 24),
                        ),
                        borderSide: BorderSide(
                          color: Theme.of(
                            context,
                          ).colorScheme.primary.withOpacity(0.6),
                          width: 1.4,
                        ),
                      ),
                      filled: true,
                      fillColor:
                          Theme.of(context).colorScheme.surfaceContainerHighest,
                      contentPadding: EdgeInsets.symmetric(
                        horizontal: ResponsiveUtils.getResponsiveSpacing(
                          context,
                          16,
                        ),
                        vertical: ResponsiveUtils.getResponsiveSpacing(
                          context,
                          12,
                        ),
                      ),
                    ),
                    minLines: 1,
                    maxLines: 4,
                    textInputAction: TextInputAction.send,
                    onSubmitted: (_) => _sendMessage(),
                  ),
                ),
                SizedBox(
                  width: ResponsiveUtils.getResponsiveSpacing(context, 8),
                ),
                // 发送按钮
                IconButton(
                  onPressed:
                      (_isLoading ||
                              (_messageController.text.trim().isEmpty &&
                                  _pendingImage == null))
                          ? null
                          : _sendMessage,
                  icon:
                      _isLoading
                          ? SizedBox(
                            width: ResponsiveUtils.getResponsiveIconSize(
                              context,
                              22,
                            ),
                            height: ResponsiveUtils.getResponsiveIconSize(
                              context,
                              22,
                            ),
                            child: CircularProgressIndicator(strokeWidth: 2),
                          )
                          : Icon(
                            Icons.send_rounded,
                            size: ResponsiveUtils.getResponsiveIconSize(
                              context,
                              26,
                            ),
                          ),
                  color: Theme.of(context).colorScheme.primary,
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  // 原顶部欢迎横幅已被 FancyHeader 替代

  // 思考中提示气泡
  Widget _buildTypingIndicator(BuildContext context) {
    final ColorScheme cs = Theme.of(context).colorScheme;
    return Align(
      alignment: Alignment.centerLeft,
      child: Container(
        margin: EdgeInsets.only(
          bottom: ResponsiveUtils.getResponsiveSpacing(context, 16),
        ),
        padding: EdgeInsets.symmetric(
          horizontal: ResponsiveUtils.getResponsiveSpacing(context, 14),
          vertical: ResponsiveUtils.getResponsiveSpacing(context, 10),
        ),
        decoration: BoxDecoration(
          color: cs.surfaceContainerHighest,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(
              ResponsiveUtils.getResponsiveRadius(context, 6),
            ),
            topRight: Radius.circular(
              ResponsiveUtils.getResponsiveRadius(context, 16),
            ),
            bottomLeft: Radius.circular(
              ResponsiveUtils.getResponsiveRadius(context, 16),
            ),
            bottomRight: Radius.circular(
              ResponsiveUtils.getResponsiveRadius(context, 16),
            ),
          ),
        ),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            SizedBox(
              width: ResponsiveUtils.getResponsiveIconSize(context, 16),
              height: ResponsiveUtils.getResponsiveIconSize(context, 16),
              child: CircularProgressIndicator(
                strokeWidth: 2,
                color: cs.primary,
              ),
            ),
            SizedBox(width: ResponsiveUtils.getResponsiveSpacing(context, 10)),
            Text(
              '正在思考…',
              style: TextStyle(color: cs.onSurface.withOpacity(0.7)),
            ),
          ],
        ),
      ),
    );
  }

  void _showImagePicker() {
    showModalBottomSheet(
      context: context,
      builder: (BuildContext context) {
        return SafeArea(
          child: Wrap(
            children: [
              ListTile(
                leading: const Icon(Icons.photo_camera),
                title: const Text('拍照'),
                onTap: () async {
                  Navigator.pop(context);
                  await _pickImage(ImageSource.camera);
                },
              ),
              ListTile(
                leading: const Icon(Icons.photo_library),
                title: const Text('从相册选择'),
                onTap: () async {
                  Navigator.pop(context);
                  await _pickImage(ImageSource.gallery);
                },
              ),
            ],
          ),
        );
      },
    );
  }

  Future<void> _pickImage(ImageSource source) async {
    try {
      final ImagePicker picker = ImagePicker();
      final XFile? image = await picker.pickImage(
        source: source,
        maxWidth: 800,
        maxHeight: 800,
        imageQuality: 80,
      );

      if (image != null) {
        // 先本地显示，紧接着上传，成功后替换为服务端URL
        setState(() {
          _pendingImage = File(image.path);
          _pendingImageUrl = null;
        });
        try {
          final uploadResp = await ApiService().uploadFile(File(image.path));
          print('🖼️ 选图后立即上传(${uploadResp.statusCode}): ${uploadResp.data}');
          if (uploadResp.statusCode == 200) {
            final data = uploadResp.data;
            // 兼容多种返回字段，优先取data.url
            final String? url =
                (data?['data']?['url'] ??
                        data?['url'] ??
                        data?['data']?['path'])
                    ?.toString();
            final String? fid = data?['data']?['fileId']?.toString();
            if (url != null && url.isNotEmpty) {
              setState(() {
                _pendingImageUrl = url;
              });
            }
            if (fid != null && fid.isNotEmpty) {
              _pendingFileId = fid;
            }
          }
        } catch (e) {
          print('❌ 选图后上传失败: $e');
        }
        // 提示
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('图片已上传，准备发送...'),
            duration: Duration(seconds: 2),
          ),
        );
      }
    } catch (e) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('选择图片失败: $e')));
    }
  }

  Future<void> _startNewSession() async {
    try {
      await _createChatSession();
      // 切换到新会话后，清空内存消息，但不删除老会话本地记录
      setState(() {
        _messages.clear();
        _messages.add(
          ChatMessage(
            text: '已开始新会话，欢迎继续提问。',
            isUser: false,
            timestamp: DateTime.now(),
          ),
        );
      });
      _scrollToBottom();
    } catch (e) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('新会话创建失败：$e')));
    }
  }

  Future<void> _showHistorySheet() async {
    final box = Hive.box('app');
    // 简单维护会话id清单：可以在创建成功时 push 进去
    final List<String> sessionIds = _loadAllSessionIds(box);
    if (sessionIds.isEmpty) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(const SnackBar(content: Text('暂无历史会话')));
      return;
    }
    await showModalBottomSheet(
      context: context,
      builder: (ctx) {
        return SafeArea(
          child: ListView.separated(
            itemCount: sessionIds.length,
            separatorBuilder: (_, __) => const Divider(height: 1),
            itemBuilder: (context, index) {
              final id = sessionIds[index];
              final key = 'aiChatMessages_' + id;
              final List<dynamic>? msgs = box.get(key) as List<dynamic>?;
              final int count = msgs?.length ?? 0;
              return ListTile(
                leading: const Icon(Icons.forum),
                title: Text('会话 $id'),
                subtitle: Text('本地消息数：$count'),
                trailing: const Icon(Icons.chevron_right),
                onTap: () {
                  Navigator.pop(context);
                  _switchToSession(id);
                },
              );
            },
          ),
        );
      },
    );
  }

  List<String> _loadAllSessionIds(Box box) {
    final List<String> ids = [];
    try {
      final List<dynamic>? saved = box.get('aiSessionIds') as List<dynamic>?;
      if (saved != null) {
        for (final s in saved) {
          final str = s?.toString();
          if (str != null && str.isNotEmpty && !ids.contains(str)) {
            ids.add(str);
          }
        }
      }
      // 确保当前会话也在列表中
      final String? cur = _sessionId ?? box.get('aiConversationId') as String?;
      if (cur != null && cur.isNotEmpty && !ids.contains(cur)) {
        ids.insert(0, cur);
      }
    } catch (_) {}
    return ids;
  }

  Future<void> _switchToSession(String conversationId) async {
    try {
      final box = Hive.box('app');
      await box.put('aiConversationId', conversationId);
      setState(() {
        _sessionId = conversationId;
        _messages.clear();
      });
      // 优先本地恢复
      final restored = _restoreChatFromLocal();
      if (!restored) {
        // 可选：远端拉取（若你希望切换时从云端同步）
        // final listResp = await ApiService().getConversationMessages(conversationId: conversationId);
        // TODO: 解析并填充
      }
      if (_messages.isEmpty) {
        _messages.add(
          ChatMessage(
            text: '已切换到会话 $conversationId',
            isUser: false,
            timestamp: DateTime.now(),
          ),
        );
      }
      _scrollToBottom();
    } catch (e) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('切换会话失败：$e')));
    }
  }

  void _sendMessage() {
    final text = _messageController.text.trim();
    // 如果没有文字且没有图片，则不发送
    if (text.isEmpty && _pendingImage == null) return;

    // 敏感词过滤：命中则拦截
    final String checkTarget = text; // 当前仅校验文本
    final String? hit = SensitiveFilter.findFirst(checkTarget);
    if (hit != null) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('包含敏感词，已拦截：$hit'),
          duration: const Duration(seconds: 2),
        ),
      );
      return;
    }

    setState(() {
      _messages.add(
        ChatMessage(
          text: text,
          image: _pendingImage,
          isUser: true,
          timestamp: DateTime.now(),
        ),
      );
      _messageController.clear();
      _pendingImage = null; // 清空待发送图片
    });

    _scrollToBottom();
    _saveChatToLocal();
    _sendToAI(text);
  }

  Future<String?> _ensureSessionId() async {
    if (_sessionId != null && _sessionId!.isNotEmpty) return _sessionId;
    try {
      final box = Hive.box('app');
      final String? savedConversationId =
          box.get('aiConversationId') as String?;
      if (savedConversationId != null && savedConversationId.isNotEmpty) {
        _sessionId = savedConversationId;
        return _sessionId;
      }
    } catch (_) {}
    await _createChatSession();
    return _sessionId;
  }

  Future<void> _sendToAI(String userText) async {
    setState(() {
      _isLoading = true;
    });

    // 追加一个占位AI消息，待拿到返回后替换
    final ChatMessage placeholder = ChatMessage(
      text: '',
      isUser: false,
      image: null,
      timestamp: DateTime.now(),
    );
    setState(() => _messages.add(placeholder));
    _scrollToBottom();

    try {
      final String? sid = await _ensureSessionId();
      if (sid == null || sid.isEmpty) {
        throw Exception('会话ID为空');
      }

      final api = ApiService();
      // 若存在待发送图片，先上传文件，打印返回，然后继续
      if (_messages.isNotEmpty) {
        // 查找刚刚追加的用户消息（上一条）是否包含图片
        final int userIndex = _messages.length >= 2 ? _messages.length - 2 : -1;
        if (userIndex >= 0) {
          final ChatMessage userMsg = _messages[userIndex];
          if (userMsg.image != null) {
            try {
              final uploadResp = await api.uploadFile(userMsg.image!);
              print('🖼️ 文件上传(${uploadResp.statusCode}): ${uploadResp.data}');
            } catch (e) {
              print('❌ 文件上传失败: $e');
            }
          }
        }
      }

      final resp = await api.sendChatMessage(
        conversationId: sid,
        message:
            _pendingFileId != null && _pendingFileId!.isNotEmpty
                ? '${userText}\n[fileId:${_pendingFileId}]'
                : userText,
      );

      if (resp.statusCode != 200) {
        setState(() {
          final int last = _messages.length - 1;
          _messages[last] = ChatMessage(
            text: '服务开小差了，请稍后再试。(${resp.statusCode})',
            isUser: false,
            image: null,
            timestamp: placeholder.timestamp,
          );
          _isLoading = false;
        });
        _scrollToBottom();
        _saveChatToLocal();
        return;
      }

      final d = resp.data;
      final String? chatId = d?['data']?['chatId']?.toString();
      if (chatId == null || chatId.isEmpty) {
        // 兜底：尝试拉取会话消息，取最后一条助手消息
        try {
          final listResp = await api.getConversationMessages(
            conversationId: sid,
          );
          print('🧰 兜底-会话消息(${listResp.statusCode}): ${listResp.data}');
          String aiText = '发送成功，但暂未获取到AI回复';
          if (listResp.statusCode == 200) {
            final dynamic body = listResp.data;
            final dynamic payload = body is Map ? body['data'] : null;
            if (payload is List && payload.isNotEmpty) {
              Map<String, dynamic>? picked;
              for (int i = payload.length - 1; i >= 0; i--) {
                final dynamic item = payload[i];
                if (item is Map) {
                  final role = item['role']?.toString();
                  final ctype = item['contentType']?.toString();
                  if (role == 'assistant' && ctype == 'text') {
                    picked = Map<String, dynamic>.from(item);
                    break;
                  }
                }
              }
              aiText = picked?['content']?.toString() ?? aiText;
            }
          }
          setState(() {
            final int last = _messages.length - 1;
            _messages[last] = ChatMessage(
              text: aiText,
              isUser: false,
              image: null,
              timestamp: placeholder.timestamp,
            );
            _isLoading = false;
          });
          _scrollToBottom();
          _saveChatToLocal();
        } catch (e) {
          setState(() {
            final int last = _messages.length - 1;
            _messages[last] = ChatMessage(
              text: '发送成功，但未返回chatId，且获取列表失败：$e',
              isUser: false,
              image: null,
              timestamp: placeholder.timestamp,
            );
            _isLoading = false;
          });
          _scrollToBottom();
          _saveChatToLocal();
        }
        return;
      }

      // 轮询查询回答状态
      final api2 = ApiService();
      const int maxAttempts = 30; // 最长约30秒
      const Duration pollDelay = Duration(seconds: 1);
      String finalText = '';
      bool finished = false;
      for (int attempt = 0; attempt < maxAttempts; attempt++) {
        try {
          final statusResp = await api2.getChatStatus(
            conversationId: sid,
            chatId: chatId,
          );
          if (statusResp.statusCode == 200) {
            final sd = statusResp.data;
            final dynamic statusRaw = sd?['data']?['status'] ?? sd?['status'];
            final String status = statusRaw?.toString().toLowerCase() ?? '';

            if (status == 'completed' ||
                status == 'success' ||
                status == 'done') {
              // 改为：根据 chatId 获取本次AI回复
              try {
                final msgResp = await api2.getChatMessages(
                  conversationId: sid,
                  chatId: chatId,
                );
                print('💬 AI回复消息(${msgResp.statusCode}): ${msgResp.data}');
                final dynamic body = msgResp.data;
                final dynamic payload = body is Map ? body['data'] : null;

                if (payload is List && payload.isNotEmpty) {
                  Map<String, dynamic>? picked;
                  for (int i = payload.length - 1; i >= 0; i--) {
                    final dynamic item = payload[i];
                    if (item is Map) {
                      final role = item['role']?.toString();
                      final type = item['type']?.toString();
                      final ctype = item['contentType']?.toString();
                      if (role == 'assistant' && ctype == 'text') {
                        picked = Map<String, dynamic>.from(item);
                        break;
                      }
                      if (type == 'answer' && ctype == 'text') {
                        picked = Map<String, dynamic>.from(item);
                        break;
                      }
                    }
                  }
                  finalText = picked?['content']?.toString() ?? '已完成，但无返回文本';
                } else if (payload is Map) {
                  finalText =
                      (payload['content'] ??
                              payload['answer'] ??
                              payload['message'] ??
                              body['msg'] ??
                              '已完成，但无返回文本')
                          .toString();
                } else {
                  finalText = '已完成，但无返回文本';
                }
              } catch (e) {
                print('❌ 获取AI回复失败: $e');
                finalText = '已完成，但获取AI回复失败';
              }
              finished = true;
              break;
            }
            if (status == 'failed' || status == 'error') {
              finalText =
                  (sd?['data']?['errorMsg'] ?? sd?['message'] ?? '生成失败')
                      .toString();
              finished = true;
              break;
            }
          }
        } catch (_) {}
        await Future.delayed(pollDelay);
      }

      if (!finished) {
        finalText = '生成超时，请稍后重试。';
      }

      setState(() {
        _isLoading = false;
      });
      _startTypingEffect(finalText, placeholder.timestamp);
    } catch (e) {
      setState(() {
        final int last = _messages.length - 1;
        _messages[last] = ChatMessage(
          text: '发送失败：$e',
          isUser: false,
          image: null,
          timestamp: DateTime.now(),
        );
        _isLoading = false;
      });
      _scrollToBottom();
      _saveChatToLocal();
    }
  }

  void _startTypingEffect(String fullText, DateTime timestamp) {
    _typingTimer?.cancel();
    String current = '';
    const int stepMs = 12; // 更快的打字速度
    int idx = 0;
    // 根据文本长度动态调整每次渲染的字符数量
    final int charsPerTick =
        fullText.length >= 300 ? 3 : (fullText.length >= 120 ? 2 : 1);
    _typingTimer = Timer.periodic(const Duration(milliseconds: stepMs), (t) {
      if (!mounted) {
        t.cancel();
        return;
      }
      if (idx >= fullText.length) {
        t.cancel();
        _saveChatToLocal();
        return;
      }
      final int nextEnd =
          (idx + charsPerTick) > fullText.length
              ? fullText.length
              : (idx + charsPerTick);
      current = fullText.substring(0, nextEnd);
      idx = nextEnd;
      setState(() {
        final int last = _messages.length - 1;
        _messages[last] = ChatMessage(
          text: current,
          isUser: false,
          image: null,
          timestamp: timestamp,
        );
      });
      _scrollToBottom();
    });
  }

  bool _restoreChatFromLocal() {
    try {
      final box = Hive.box('app');
      final String? cid = _sessionId ?? box.get('aiConversationId') as String?;
      if (cid == null || cid.isEmpty) return false;
      final String key = 'aiChatMessages_' + cid;
      final dynamic raw = box.get(key);
      if (raw is List) {
        _messages.clear();
        for (final item in raw) {
          if (item is Map) {
            final String text = (item['text'] ?? '').toString();
            final bool isUser = (item['isUser'] ?? false) == true;
            final int ts = int.tryParse((item['ts'] ?? '0').toString()) ?? 0;
            final String? imagePath = item['imagePath']?.toString();
            _messages.add(
              ChatMessage(
                text: text,
                isUser: isUser,
                image:
                    (imagePath != null && imagePath.isNotEmpty)
                        ? File(imagePath)
                        : null,
                timestamp:
                    ts > 0
                        ? DateTime.fromMillisecondsSinceEpoch(ts)
                        : DateTime.now(),
              ),
            );
          }
        }
        return _messages.isNotEmpty;
      }
    } catch (_) {}
    return false;
  }

  Future<void> _saveChatToLocal() async {
    try {
      final box = Hive.box('app');
      final String? cid = _sessionId ?? box.get('aiConversationId') as String?;
      if (cid == null || cid.isEmpty) return;
      _addSessionIdToList(cid);
      final String key = 'aiChatMessages_' + cid;
      final List<Map<String, dynamic>> data = _messages
          .map(
            (m) => {
              'text': m.text,
              'isUser': m.isUser,
              'ts': m.timestamp.millisecondsSinceEpoch,
              'imagePath': m.image?.path,
            },
          )
          .toList(growable: false);
      await box.put(key, data);
    } catch (_) {}
  }

  void _addSessionIdToList(String conversationId) {
    final box = Hive.box('app');
    final List<dynamic>? saved = box.get('aiSessionIds') as List<dynamic>?;
    final List<String> ids = [];
    if (saved != null) {
      for (final s in saved) {
        final str = s?.toString();
        if (str != null && str.isNotEmpty && !ids.contains(str)) {
          ids.add(str);
        }
      }
    }
    if (!ids.contains(conversationId)) {
      ids.add(conversationId);
      box.put('aiSessionIds', ids);
    }
  }

  void _scrollToBottom() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_scrollController.hasClients) {
        _scrollController.animateTo(
          _scrollController.position.maxScrollExtent,
          duration: const Duration(milliseconds: 300),
          curve: Curves.easeOut,
        );
      }
    });
  }

  // 显示语音设置面板
  void _showTTSSettings(BuildContext context) {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      builder:
          (context) => Container(
            decoration: BoxDecoration(
              color: Theme.of(context).colorScheme.surface,
              borderRadius: const BorderRadius.vertical(
                top: Radius.circular(20),
              ),
            ),
            padding: EdgeInsets.only(
              bottom: MediaQuery.of(context).viewInsets.bottom,
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                // 拖拽指示器
                Container(
                  margin: const EdgeInsets.only(top: 8),
                  width: 40,
                  height: 4,
                  decoration: BoxDecoration(
                    color: Theme.of(
                      context,
                    ).colorScheme.onSurface.withOpacity(0.3),
                    borderRadius: BorderRadius.circular(2),
                  ),
                ),
                // 语音设置面板
                const TTSSettingsPanel(),
                SizedBox(height: MediaQuery.of(context).padding.bottom + 16),
              ],
            ),
          ),
    );
  }

  String _formatTime(DateTime time) {
    return '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}';
  }

  // 创建AI聊天会话
  Future<void> _createChatSession() async {
    try {
      final apiService = ApiService();
      final response = await apiService.createChatSession();

      if (response.statusCode == 200) {
        final data = response.data;
        print('🔍 AI聊天会话创建响应: $data');
        if (data != null && data['code'] == 200) {
          // 优先使用 conversationId，兼容 sessionId/id
          final dynamic rawId =
              data['data']?['conversationId'] ??
              data['data']?['sessionId'] ??
              data['data']?['id'];
          final String? conversationId = rawId?.toString();

          if (conversationId != null && conversationId.isNotEmpty) {
            final box = Hive.box('app');
            await box.put('aiConversationId', conversationId);
            setState(() {
              _sessionId = conversationId;
            });
            // 维护本地会话清单
            try {
              _addSessionIdToList(conversationId);
            } catch (_) {}
            print('✅ AI聊天会话创建成功，会话ID: $conversationId (已保存本地)');
          } else {
            print('❌ AI聊天会话创建失败：未获取到会话ID');
          }
        } else {
          print('❌ AI聊天会话创建失败: ${data?['message'] ?? '未知错误'}');
        }
      } else {
        print('❌ AI聊天会话创建失败，状态码: ${response.statusCode}');
      }
    } catch (e) {
      print('❌ AI聊天会话创建异常: $e');
    }
  }
}

class ChatMessage {
  final String text;
  final File? image;
  final bool isUser;
  final DateTime timestamp;

  ChatMessage({
    required this.text,
    this.image,
    required this.isUser,
    required this.timestamp,
  });
}
